using System;
using System.Diagnostics;

namespace DNNContentBuilder
{
	/// <summary>
	/// Validates that arguments are not null, not empty, or that certain
	/// criteria are met.
	/// </summary>
	internal sealed class ArgumentValidator
	{
		/// <summary>
		/// Prevents public instantiation of this class.
		/// </summary>
		private ArgumentValidator()
		{
		}
		
		private const string resource = "~/DesktopModules/DNNContentBuilder/App_LocalResources/ResourceEngine";
/*
		private const string eventResource = "~/DesktopModules/DNNContentBuilder/App_LocalResources/MetaDataEvent";
*/

	    /// <summary>
		/// Asserts that the variable is not null.
		/// </summary>
		/// <param name="variable"></param>
		/// <exception cref="ArgumentNullException">If the variable is null</exception>
		/// <param name="variableName"></param>
		[DebuggerHidden]
		public static void CheckForNullReference(object variable, string variableName)
		{
			if (variableName == null)
			{
				throw new ArgumentNullException("variableName");
			}

			if (variable == null)
			{
				throw new ArgumentNullException(variableName);
			}
		}

		/// <summary>
		/// Asserts that the supplied string is not null and has a non-zero length
		/// </summary>
		/// <param name="variable"></param>
		/// <param name="variableName"></param>
		[DebuggerHidden]
		public static void CheckForEmptyString(string variable, string variableName)
		{
			CheckForNullReference(variable, variableName);

			if (variable.Length <= 0)
			{
				throw new ArgumentException(Commons.GetLocalizedString("ERR_ZERO_LENGTH_PARAMETER",resource), variableName);
			}
		}

		/// <summary>
		/// Asserts that the value is of the expected type.
		/// </summary>
		/// <param name="variable"></param>
		/// <param name="variableName"></param>
		/// <param name="expectedType"></param>
		/// <exception cref="ArgumentException">When the value is not of the specified type.</exception>
		[DebuggerHidden]
		public static void CheckForExpectedType(object variable, string variableName, Type expectedType)
		{
			CheckForNullReference(variableName, "variableName");
			CheckForNullReference(expectedType, "expectedType");

			if (variable != null && variable.GetType() != expectedType)
			{
				throw new ArgumentException(Commons.GetLocalizedString("ERR_INVALID_TYPE",resource), variableName);
			}
		}

		/// <summary>
		/// Asserts that the variable is not null. Throws exception otherwise.
		/// </summary>
		/// <param name="variable"></param>
#pragma warning disable 1574
		/// <param name="key"></param>
#pragma warning restore 1574
		/// <exception cref="ApplicationException">If the value is null</exception>
		[DebuggerHidden]
		public static void AssertNotNull(object variable, string resourceEngineKey, params object[] args)
		{
			if (variable == null)
			{
				string message = String.Format(Commons.GetLocalizedString(resourceEngineKey,resource), args);
				throw new ApplicationException(message);
			}
		}

		/// <summary>
		/// Asserts that the object is of an expected type. Throws exception otherwise.
		/// </summary>
		/// <param name="variable"></param>
		/// <param name="expectedType"></param>
		/// <param name="resourceEngineKey"></param>
		/// <exception cref="ApplicationException">When the variable is not of the expected type.</exception>
		[DebuggerHidden]
		public static void AssertExpectedType(object variable, Type expectedType, string resourceEngineKey)
		{
			CheckForNullReference(variable, "variable");
			CheckForNullReference(expectedType, "expectedType");

			Type type = variable.GetType();

			if (type != expectedType && 
				type.IsSubclassOf(expectedType) == false && 
				type.GetInterface(expectedType.Name) == null)
			{
				throw new ApplicationException(Commons.GetLocalizedString(resourceEngineKey, resource));
			}
		}
	}
}
